<?php


namespace support;


use common\exception\LogicException;
use common\model\DelayOrderTaskModel;
use common\model\EntityEpisodeRelationModel;
use common\model\EntityModel;
use common\model\PlanModel;
use common\model\ReviewFeedbackEntityModel;
use common\model\ReviewFeedbackModel;
use common\model\ReviewRequestModel;
use common\model\StatusModel;
use common\model\StepCategoryModel;
use common\model\TaskModel;
use common\service\EpisodeAllocationService;
use common\service\StatusService;
use common\service\TenantService;
use think\module\Module;

trait EntityTaskFilterParser
{
    /** @var array 表名列表 */
    public $tableList = [];

    /**
     * 追加表名
     * @param $tableName
     * @return void
     */
    public function appendTableList($tableName)
    {
        if (!in_array($tableName, $this->tableList)) {
            $this->tableList[] = $tableName;
        }
    }

    /**
     * 清空表名
     * @return void
     */
    public function destroyTableList()
    {
        $this->tableList = [];
    }

    /**
     * 保留多层固定字段筛选
     * @param $filter
     * @param $fixTableName
     * @param $res
     */
    public function keepFixFieldsFilter($filter, $fixTableName, &$res)
    {
        if (empty($filter)) {
            return;
        }
        foreach ($filter as $filterKey => $filterItem) {
            if (is_numeric($filterKey)) {
                $tmpFilter = [];
                $this->keepFixFieldsFilter($filterItem, $fixTableName, $tmpFilter);
                $res[$filterKey] = $tmpFilter;
            } else if ($filterKey === '_logic') {
                $res[$filterKey] = $filterItem;
            } else {
                if (strstr($filterKey, '.') === false) {
                    $fixedFields = array_keys(Module::$moduleDictData['field_index_by_code'][$fixTableName]['fixed'] ?? []);
                    if (in_array($filterKey, $fixedFields)) {
                        // 固定字段
                        $res[$fixTableName . '.' . $filterKey] = $filterItem;
                        $this->appendTableList($fixTableName);
                    }
                    continue;
                } else {
                    $fieldData = explode('.', $filterKey);
                    $currentModule = Module::$moduleDictData['field_index_by_code'][$fieldData[0]] ?? null;
                    if (empty($currentModule)) {
                        // 模块不存在
                        continue;
                    }
                    $this->appendTableList($fieldData[0]);
                    // 固定字段
                    $fixedFields = array_keys($currentModule['fixed'] ?? []);
                    if (!in_array($fieldData[1], $fixedFields)) {
                        continue;
                    }
                    $res[$filterKey] = $filterItem;
                }
            }
        }
    }

    /**
     * 解析内部执行人筛选
     * @param $executorFilter
     * @param $insideExecutor
     */
    public function parseInsideExecutorFilter(&$executorFilter, $insideExecutor)
    {
        $insideExecutor = array_column($insideExecutor, 'user_id');
        if (count($insideExecutor)) {
            $executorFilter[] = [
                'task.department_id' => ['IN', $insideExecutor],
            ];
            $this->appendTableList('task');
        }
    }

    /**
     * 是否是标准制作
     * @return false
     */
    public function isStandardProduction()
    {
        return false;
    }

    /**
     * 解析资产任务 多模块资产筛选条件
     * @param array $filter
     * @return array
     */
    public function parseMultipleEntityTaskFilter(array $filter, $nodeMode = false)
    {
        $this->destroyTableList();
        $entityFilter = [];
        // 保留固定字段
        $this->keepFixFieldsFilter($filter, 'entity', $entityFilter);
        $today = $filter['today'] ?? null;
        $taskName = $filter['task_name'] ?? null;
        $entityNameSearch = $filter['entity_name'] ?? '';
        $taskStatusSearch = $filter['assign_status'] ?? '';
        $showingsNumber = $filter['showings_number'] ?? '';
        $taskStepCategorySearch = $filter['step_category_id'] ?? '';
        $taskStepCategoryCodeSearch = $filter['step_category_code'] ?? '';
        $planStartTimeSearch = $filter['plan_start_time'] ?? '';
        $planEndTimeSearch = $filter['plan_end_time'] ?? '';
        $executorSearch = $filter['executor'] ?? [];
        $gradeSearch = $filter['grade'] ?? '';
        $categoryNameSearch = $filter['category_name'] ?? '';
        $showingsNumberListSearch = $filter['showings_number_list'] ?? [];
        $moduleSearchList = $filter['module_code'] ?? [];
        $taskStatusFilter = $filter['task_status'] ?? null;
        $taskDealStatusSearch = $filter['deal_status'] ?? [];
        $todoStepCategoryId = $filter['todo_step_category_id'] ?? $filter['todo_step_category_id_list'] ?? null;
        $todoEpisodeId = $filter['todo_episode_id'] ?? null;
        $taskMemberStatus = $filter['task_member_status'] ?? null;
        $taskMemberPartner = $filter['task_member_partner'] ?? null;
        $taskMemberUser = $filter['task_member_user'] ?? null;
        $taskTaskMemberStatusFilter = $filter['task_task_member_status'] ?? null;
        $departmentIdUserFilter = $filter['department_id_user_filter'] ?? null;
        $timeSearch = $filter['time_search'] ?? [];
        $timeSearchType = $filter['time_search_type'] ?? 'done';
        $onlyNotDone = $filter['only_not_done'] ?? 'no';
        $standardOrOther = $filter['standard_or_other'] ?? 'no';
        $isAbnormal = !empty($filter['is_abnormal']) && $filter['is_abnormal'] == 'yes';
        $projectId = $filter['project_id'] ?? $filter['task.project_id'] ?? $filter['entity.project_id'] ?? null;
        $isOverdue = !empty($filter['is_overdue']) && $filter['is_overdue'] === 'yes';
        $isLock = $filter['task_is_lock'] ?? null;
        $demandOrderId = $filter['demand_order_id'] ?? null;
        $delayOrderId = $filter['delay_order_id'] ?? null;

        if ($isAbnormal) {
            $notStartedStatusList = StatusService::getInstance()->getNotStartedStatus();
            $closedStatus = StatusService::getInstance()->getTaskDefaultClosedStatus();
            $doneStatus = StatusService::getInstance()->getTaskDoneStatus();
            $publishStatus = StatusService::getInstance()->getTaskReadyToPublishStatus();
            // 异常
            // 工序任务 逾期未完成 到了计划截至时间(未开始,未分配)
            // 待办任务 逾期未完成
            $entityFilter[] = [
                [
                    [
                        'task.step_type' => TaskModel::STEP_TYPE_STEP,
                        [
                            'task.assign_status' => 'default',
                            "task.json->>'$.task_status'" => ['IN', implode(',', array_column($notStartedStatusList, 'id'))],
                            '_logic' => 'OR',
                        ],
                        'task.plan_end_time' => ['BETWEEN', [1, time()]],
                        "task.json->>'$.task_status'" => ['NOT IN', [$publishStatus['id'], $doneStatus['id'], $closedStatus['id']]],
                    ],
                    [
                        'task.plan_end_time' => ['BETWEEN', [1, time()]],
                        "task.json->>'$.task_status'" => ['NOT IN', [$publishStatus['id'], $doneStatus['id'], $closedStatus['id']]],
                    ],
                    ['task_work_order_temp.task_id' => ['EXP', 'IS NOT NULL'],],
                    '_logic' => 'or',
                ],
                [
                    "task.json->>'$.task_status'" => ['NEQ', $closedStatus['id']]
                ],
            ];
            $this->appendTableList('task');
            $this->appendTableList('task_work_order_temp');
        }
        if ($isOverdue) {
            $doneStatus = StatusService::getInstance()->getTaskDoneStatus();
            $entityFilter[] = [
                'task.end_time' => 0,
                'task.plan_end_time' => ['BETWEEN', [1, time()]],
                "task.json->>'$.task_status'" => ['NEQ', $doneStatus['id']]
            ];
            $this->appendTableList('task');
        }

        if (!empty($showingsNumberListSearch)) {
            $entityFilter["entity.showings_number"] = ['IN', $showingsNumberListSearch];
            $this->appendTableList('entity');
        }
        if (!empty($gradeSearch)) {
            $entityFilter["JSON_UNQUOTE(JSON_EXTRACT(entity.json, CONCAT('$.',module.code,'_grade')))"] = $gradeSearch;
            $this->appendTableList('module');
            $this->appendTableList('entity');
        }
        if (!empty($categoryNameSearch)) {
            $entityFilter["JSON_UNQUOTE(JSON_EXTRACT(entity.json, CONCAT('$.',module.code,'_category')))"] = $categoryNameSearch;
            $this->appendTableList('module');
            $this->appendTableList('entity');
        }
        if (!empty($taskStatusSearch)) {
            $entityFilter['task.assign_status'] = $taskStatusSearch;
            $this->appendTableList('task');
        }
        if (!empty($taskStatusFilter)) {
            $statusIdList = model(StatusModel::class)->where(['code' => $taskStatusFilter])->field('id')->select();
            if (count($statusIdList) > 0) {
                $entityFilter["JSON_UNQUOTE(JSON_EXTRACT(task.json,'$.task_status'))"] = ['IN', array_column($statusIdList, 'id')];
            } else {
                $entityFilter["JSON_UNQUOTE(JSON_EXTRACT(task.json,'$.task_status'))"] = ['EXP', 'IS NULL'];
            }
            $this->appendTableList('task');
        }
        if (!empty($entityNameSearch)) {
            $entityFilter['entity.name'] = $entityNameSearch;
            $this->appendTableList('entity');
        }
        if (!empty($taskName)) {
            $entityFilter[] = [
                'task.name' => $taskName,
                'entity.name' => $taskName,
                '_logic' => 'or',
            ];
            $this->appendTableList('entity');
            $this->appendTableList('task');
        }
        if (!empty($showingsNumber)) {
            $entityFilter['entity.showings_number'] = $showingsNumber;
            $this->appendTableList('entity');
        }
        if (!empty($taskStepCategorySearch)) {
            $stepCategoryList = model(StepCategoryModel::class)->where(['id' => $taskStepCategorySearch])->select();
            $stepCategoryIdList = array_column($stepCategoryList, 'id');
            if (!empty($stepCategoryList)) {
                $childrenStepCategoryList = model(StepCategoryModel::class)->where(['parent_id' => ['IN', implode(',', array_column($stepCategoryList, 'id'))]])->select();
                if (!empty($childrenStepCategoryList)) {
                    $stepCategoryIdList = array_merge($stepCategoryIdList, array_column($childrenStepCategoryList, 'id'));
                }
                $entityFilter['task.step_category_id'] = ['IN', implode(',', $stepCategoryIdList)];
            }
            $this->appendTableList('task');
        }
        if (!empty($taskStepCategoryCodeSearch)) {
            $stepCategoryIdList = model(StepCategoryModel::class)->where(['code' => $taskStepCategoryCodeSearch])->field('id')->column('id');
            $entityFilter['task.step_category_id'] = ['IN', implode(',', $stepCategoryIdList)];
            $this->appendTableList('task');
        }
        if (!empty($planStartTimeSearch)) {
            $entityFilter[] = [
                'task.plan_start_time' => $planStartTimeSearch,
                'entity.plan_start_time' => $planStartTimeSearch,
                '_logic' => "or"
            ];
            $this->appendTableList('entity');
            $this->appendTableList('task');
        }
        if (!empty($planEndTimeSearch)) {
            $entityFilter[] = [
                'task.plan_end_time' => $planEndTimeSearch,
                'entity.plan_end_time' => $planEndTimeSearch,
                '_logic' => "or"
            ];
            $this->appendTableList('entity');
            $this->appendTableList('task');
        }
        if (!empty($executorSearch)) {
            $executorFilter = [];
            $insideExecutor = [];
            $outsideExecutor = [];
            $tenantGroupExecutor = [];
            foreach ($executorSearch as $item) {
                if ($item['type'] === 'inside') {
                    $insideExecutor[] = $item;
                }
                if ($item['type'] === 'outside') {
                    $outsideExecutor[] = $item;
                }
                if ($item['type'] === 'tenant_group') {
                    $tenantGroupExecutor[] = $item;
                }
            }

            if (!empty($insideExecutor)) {
                $this->parseInsideExecutorFilter($executorFilter, $insideExecutor);
            }
            if (!empty($outsideExecutor)) {
                $outsideExecutor = array_column($outsideExecutor, 'from_tenant_id');
                $executorFilter[] = [
                    'task.executor_tenant_id' => ['IN', implode(',', $outsideExecutor)],
                    'task.executor_type' => 'outside'
                ];
                $this->appendTableList('task');
            }
            if (!empty($tenantGroupExecutor)) {
                $tenantGroupExecutor = array_column($tenantGroupExecutor, 'from_tenant_id');
                $executorFilter[] = [
                    'task.executor_tenant_id' => ['IN', implode(',', $tenantGroupExecutor)],
                    'task.executor_type' => 'tenant_group'
                ];
                $this->appendTableList('task');
            }

            if (count($executorFilter) > 1) {
                $executorFilter['_logic'] = 'or';
            }
            if (!empty($executorFilter)) {
                $entityFilter[] = $executorFilter;
            }
        }

        if (!empty($moduleSearchList)) {
            $entityFilter['module.code'] = $moduleSearchList;
            $this->appendTableList('module');
        }

        if (!empty($taskDealStatusSearch)) {
            $entityFilter['task.deal_status'] = $taskDealStatusSearch;
            $this->appendTableList('task');
        }

        if (!empty($today)) {
            $entityFilter[] = $this->getTodayTaskFilter();
            $this->appendTableList('task');
        }

        // 待办分类筛选
        if (!empty($todoStepCategoryId)) {
            if ($standardOrOther === 'yes') {
                if (is_array($todoStepCategoryId) && !empty($todoStepCategoryId[0]) && $todoStepCategoryId[0] === 'IN') {
                    $todoStepCategoryId = implode(',', $todoStepCategoryId[1]);
                } else if (is_array($todoStepCategoryId)) {
                    $todoStepCategoryId = implode(',', $todoStepCategoryId);
                }
                $du = TenantService::getInstance()->selectDepartmentUser(request()->getTenantId(), [
                    'param' => [
                        'department_step_category_ids' => $todoStepCategoryId
                    ]
                ]);
                $saasUserIdList = array_column($du['rows'], 'saas_user_id');
                if (empty($saasUserIdList)) {
                    $entityFilter = ['task.id' => 0];
                } else {
                    $entityFilter[] = [
                        'task_member.partner' => ['IN', implode(',', $saasUserIdList)],
                    ];
                    $this->appendTableList('task_member');
                }
            } else {
                $entityFilter[] = [
                    'r_step_category.link_id' => $todoStepCategoryId
                ];
                $this->appendTableList('r_step_category');
            }
        }

        // 待办分类筛选
        if (!empty($todoEpisodeId)) {
            $entityFilter[] = [
                "r_episode.link_id" => $todoEpisodeId
            ];
            $this->appendTableList('r_episode');
        }

        if (!empty($taskMemberStatus)) {
            $statusList = StatusService::getInstance()->getList(['code' => $taskMemberStatus], 'id');
            if (!empty($statusList)) {
                $entityFilter[] = [
                    'task_member.status' => ['IN', array_column($statusList, 'id')],
                ];
                $this->appendTableList('task_member');
            }
        }

        if (!empty($taskMemberPartner)) {
            $entityFilter[] = [
                'task_member.partner' => $taskMemberPartner,
            ];
            $this->appendTableList('task_member');
        }

        if (!empty($taskMemberUser)) {
            $entityFilter[] = [
                'task_member.user_id' => $taskMemberUser,
            ];
            $this->appendTableList('task_member');
        }
        // 混合状态筛选
        if (!empty($taskTaskMemberStatusFilter)) {
            $statusList = StatusService::getInstance()->getList(['code' => $taskTaskMemberStatusFilter], 'id');
            if (!empty($statusList)) {
                $statusList = implode(',', array_column($statusList, 'id'));
                $entityFilter[] = [
                    [
                        'task.entity_module_id' => module_by_code('todo')['id'],
                        'task_member.status' => ['IN', $statusList],
                    ],
                    [
                        'task.step_type' => ['IN', [TaskModel::STEP_TYPE_STEP, TaskModel::STEP_TYPE_STEP_CATEGORY]],
                        "task.json->>'$.task_status'" => ['IN', $statusList],
                    ],
                    '_logic' => 'OR'
                ];
                $this->appendTableList('task_member');
                $this->appendTableList('task');
            }
        }

        if (!empty($departmentIdUserFilter)) {
            // todo 分页数据问题
            $du = TenantService::getInstance()->selectDepartmentUser(request()->getTenantId(), [
                'param' => [
                    'filter' => [
                        'department_id' => $departmentIdUserFilter,
                    ]
                ]
            ]);
            $saasUserIdList = array_column($du['rows'], 'saas_user_id');
            if (empty($saasUserIdList)) {
                $entityFilter = ['task.id' => 0];
            } else {
                $entityFilter[] = [
                    'task_member.partner' => ['IN', implode(',', $saasUserIdList)],
                ];
            }
            $this->appendTableList('task_member');
        }

        if ($nodeMode) {
            $this->appendTableList('task');
        } else if (!empty($timeSearch)) {
            switch ($timeSearchType) {
                case 'in_progress_full':
                    // 我的任务 - 日视图 - 进行中 - 特殊条件
                    $entityFilter[] = [
                        "task.json->>'$.task_status'" => [
                            'NOT IN',
                            StatusService::getInstance()->byCodeMap([
                                'closed', 'final', 'ready_to_publish',
                                'remake',
                                'submitted', 'wait_for_party_a_review', 'wait_partyb_submit',
                            ], false, 'id')
                        ],
                        [
                            '_logic' => 'OR',
                            'task.plan_end_time' => ["BETWEEN", $timeSearch],
                            "task.json->>'$.task_status'" => ['NOT IN', StatusService::getInstance()->byCodeMap(["not_started", "ready_to_start", "wait_assemble", "draft"], false, 'id')],
                        ]
                    ];
                    $this->appendTableList('task');
                    break;
                case 'in_progress_done':
                    // 我的任务 - 日视图 - 已完成 - 特殊条件
                    $entityFilter[] = [
                        [
                            '_logic' => 'OR',
                            'task.end_time' => ["BETWEEN", $timeSearch],
                            'task.plan_end_time' => ["BETWEEN", $timeSearch],
                        ],
                        "task.json->>'$.task_status'" => ['IN', StatusService::getInstance()->byCodeMap(['final', 'ready_to_publish'], false, 'id')],
                    ];
                    $this->appendTableList('task');
                    break;
                case 'delivery':
//                $entityFilter[] = $this->getDeliveryFilter($timeSearch, $projectId, $todoStepCategoryId);
                    $entityFilter[] = [
                        'task.plan_delivery_time' => ["BETWEEN", $timeSearch],
                    ];
                    break;
                case 'in_plan_delivery':
                    $doneStatus = StatusService::getInstance()->getTaskDoneStatus();
                    $entityFilter[] = [
                        'task.plan_delivery_time' => ["BETWEEN", $timeSearch],
                        "task.json->>'$.task_status'" => $doneStatus['id'],
                    ];
                    break;
                case 'history_outside_plan_delivery':
                case 'outside_plan_delivery':
                    $doneStatus = StatusService::getInstance()->getTaskDoneStatus();
                    $entityFilter[] = [
                        'task.delivery_time' => ["BETWEEN", $timeSearch],
                        'task.plan_delivery_time' => ["NOT BETWEEN", $timeSearch],
                        "task.json->>'$.task_status'" => $doneStatus['id'],
                    ];
                    break;
                case 'actually_delivery':
                    $doneStatus = StatusService::getInstance()->getTaskDoneStatus();
                    $entityFilter[] = [
                        'task.delivery_time' => ["BETWEEN", $timeSearch],
                        "task.json->>'$.task_status'" => $doneStatus['id'],
                    ];
                    break;
                case 'history_delivery':
                    // 历史计划交付 查询逻辑在实际的查询哪里做union查询
//                    $entityFilter[] = [
//                        'task.plan_delivery_time' => ["BETWEEN", $timeSearch],
//                    ];
//                    $this->appendTableList('task');
                    break;
                case 'history_in_plan_delivery':
                    // 计划内交付
                    $doneStatus = StatusService::getInstance()->getTaskDoneStatus();
                    $entityFilter[] = [
                        '_logic' => 'OR',
                        [
                            'task.plan_delivery_time' => ["BETWEEN", $timeSearch],
                            "task.json->>'$.task_status'" => $doneStatus['id'],
                        ],
                        [
                            'version.plan_delivery_time' => ["BETWEEN", $timeSearch],
                            'version.published' => ["GT", 0],
                        ],
                    ];
                    $this->appendTableList('version');
                    $this->appendTableList('task');
                    break;
                case 'actually_done':
                    $doneStatus = StatusService::getInstance()->getTaskDoneStatus();
                    $publishStatus = StatusService::getInstance()->getTaskReadyToPublishStatus();
                    $entityFilter[] = [
                        'task.end_time' => ["BETWEEN", $timeSearch],
                        "task.json->>'$.task_status'" => ['IN', [$doneStatus['id'], $publishStatus['id']]],
                    ];
                    $this->appendTableList('task');
                    break;
                case 'done':
                    $entityFilter[] = [
                        'task.plan_end_time' => ["BETWEEN", $timeSearch]
                    ];
                    $this->appendTableList('task');
                    break;
                case 'in_plan_done':
                    $doneStatus = StatusService::getInstance()->getTaskDoneStatus();
                    $publishStatus = StatusService::getInstance()->getTaskReadyToPublishStatus();
                    $entityFilter[] = [
                        'task.plan_end_time' => ["BETWEEN", $timeSearch],
                        "task.json->>'$.task_status'" => ['IN', [$doneStatus['id'], $publishStatus['id']]],
                    ];
                    $this->appendTableList('task');
                    break;
                case 'history_in_plan_not_done':
                case 'in_plan_not_done':
                    $doneStatus = StatusService::getInstance()->getTaskDoneStatus();
                    $closedStatus = StatusService::getInstance()->getTaskDefaultClosedStatus();
                    $publishStatus = StatusService::getInstance()->getTaskReadyToPublishStatus();
                    $entityFilter[] = [
                        'task.plan_end_time' => ["BETWEEN", $timeSearch],
                        "task.json->>'$.task_status'" => ['NOT IN', [$closedStatus['id'], $doneStatus['id'], $publishStatus['id']]],
                    ];
                    $this->appendTableList('task');
                    break;
                case 'history_outside_plan_done':
                case 'outside_plan_done':
                    $doneStatus = StatusService::getInstance()->getTaskDoneStatus();
                    $publishStatus = StatusService::getInstance()->getTaskReadyToPublishStatus();
                    $entityFilter[] = [
                        'task.end_time' => ["BETWEEN", $timeSearch],
                        'task.plan_end_time' => ["NOT BETWEEN", $timeSearch],
                        "task.json->>'$.task_status'" => ['IN', [$doneStatus['id'], $publishStatus['id']]],
                    ];
                    $this->appendTableList('task');
                    break;
                case 'history_done':
                    // 历史计划完成 查询逻辑在实际的查询哪里做union查询
//                    $entityFilter[] = [
//                        'task.plan_end_time' => ["BETWEEN", $timeSearch],
//                    ];
//                    $this->appendTableList('task');
                    break;
                case 'history_in_plan_done':
                    // 历史计划内完成
                    $doneStatus = StatusService::getInstance()->getTaskDoneStatus();
                    $publishStatus = StatusService::getInstance()->getTaskReadyToPublishStatus();
                    $entityFilter[] = [
                        [
                            '_logic' => 'OR',
                            [
                                'task.plan_end_time' => ["BETWEEN", $timeSearch],
                                "task.json->>'$.task_status'" => ['IN', [$doneStatus['id'], $publishStatus['id']]],
                            ],
                            [
                                'version.plan_end_time' => ["BETWEEN", $timeSearch],
                                'version.end_time' => ['GT', 0],
                            ],
                        ],
                    ];
                    $this->appendTableList('task');
                    $this->appendTableList('version');
                    break;
                case 'demand_add':
                    $entityFilter[] = [
                        'task.created' => ["BETWEEN", $timeSearch],
                        "json_unquote(json_extract(task.json, '$.task_is_append'))" => "yes"
                    ];
                    $this->appendTableList('task');
                    break;
                case 'delay_created':
                    $reviewRequestFilter = [
                        'created' => ["BETWEEN", $timeSearch]
                    ];

                    if (!empty($projectId)) {
                        $reviewRequestFilter['project_id'] = $projectId;
                    }
                    if (!empty($todoStepCategoryId)) {
                        $reviewRequestFilter['step_category_id'] = $todoStepCategoryId;
                    }
                    if (!empty($todoEpisodeId)) {
                        $reviewRequestFilter['episode_id'] = $todoEpisodeId;
                    }

                    $taskIds = model(DelayOrderTaskModel::class)
                        ->where($reviewRequestFilter)
                        ->field('task_id')
                        ->distinct(true)
                        ->column("task_id");

                    if (!empty($taskIds)) {
                        $entityFilter[] = [
                            'task.id' => ["IN", $taskIds]
                        ];
                    } else {
                        $entityFilter = ['task.id' => 0];
                        $this->appendTableList('task');
                    }
                    break;
                case 'delivery_and_plan':
//                $df = $this->getDeliveryFilter($timeSearch, $projectId, $todoStepCategoryId);
                    $entityFilter[] = [
                        ['task.plan_end_time' => ["BETWEEN", $timeSearch]],
                        ['task.plan_delivery_time' => ["BETWEEN", $timeSearch]],
                        '_logic' => 'OR',
                    ];
                    $this->appendTableList('task');
                    break;
                case 'in_plan_overdue':
                    $doneStatus = StatusService::getInstance()->getTaskDoneStatus();
                    $entityFilter[] = [
                        'task.plan_end_time' => ['BETWEEN', $timeSearch],
                        [
                            "_logic" => 'OR',
                            [
                                "_string" => "task.end_time > task.plan_end_time",
                            ],
                            "task.json->>'$.task_status'" => ['NEQ', $doneStatus['id']]
                        ]
                    ];
                    $this->appendTableList('task');
                    break;
            }
        }
        if ($onlyNotDone === 'yes') {
            $doneStatus = StatusService::getInstance()->getTaskDoneStatus();
            $publishStatus = StatusService::getInstance()->getTaskReadyToPublishStatus();
            $closedStatus = StatusService::getInstance()->getTaskDefaultClosedStatus();

            if (!empty($timeSearchType) && $timeSearchType === 'delivery') {
                $entityFilter[] = [
                    "task.json->>'$.task_status'" => ["NOT IN", [$doneStatus['id'], $closedStatus['id']]],
                ];
            } else {
                $entityFilter[] = [
                    "task.json->>'$.task_status'" => ["NOT IN", [$publishStatus['id'], $doneStatus['id'], $closedStatus['id']]],
                ];
            }
            $this->appendTableList('task');
        }

        if (!empty($isLock)) {
            $lockFilter = [
                ["JSON_UNQUOTE(JSON_EXTRACT(task.json,'$.is_lock'))" => $isLock],
            ];

            if ($isLock === "no") {
                $lockFilter[] = ["JSON_UNQUOTE(JSON_EXTRACT(task.json,'$.is_lock'))" => ['EXP', 'IS NULL']];
                $lockFilter["_logic"] = "OR";
            }
            $entityFilter[] = $lockFilter;
            $this->appendTableList('task');
        }

        //需求单id
        if (!empty($demandOrderId)) {
            $reviewFeedbackEntityIds = model(ReviewFeedbackEntityModel::class)
                ->where(['review_feedback_entity.review_feedback_id' => $demandOrderId])
                ->field("entity_id")
                ->column("entity_id");
            if (!empty($reviewFeedbackEntityIds)) {
                $reviewFeedbackEntityIds = array_unique($reviewFeedbackEntityIds);
                $entityFilter[] = [
                    'task.source_entity_id' => ["IN", $reviewFeedbackEntityIds]
                ];
            } else {
                $entityFilter = ['task.id' => 0];
            }
            $this->appendTableList('task');
        }

        //延期单id
        if (!empty($delayOrderId)) {
            $delayOrderTaskIds = model(DelayOrderTaskModel::class)
                ->where(['delay_order_id' => $delayOrderId, 'type' => ['in', [DelayOrderTaskModel::TYPE_REQUEST_DELAY, DelayOrderTaskModel::TYPE_WORK_ORDER]] ])
                ->field("task_id")
                ->column("task_id");
            if (!empty($delayOrderTaskIds)) {
                $delayOrderTaskIds = array_unique($delayOrderTaskIds);
                $entityFilter[] = [
                    'task.id' => ["IN", $delayOrderTaskIds]
                ];
            } else {
                $entityFilter = ['task.id' => 0];
            }
            $this->appendTableList('task');
        }
        return $entityFilter;
    }

    /**
     * 查询交付筛选条件
     * @param $timeSearch
     * @param $projectId
     * @param $todoStepCategoryId
     * @return array|array[]|int[]|mixed
     */
    public function getDeliveryFilter($timeSearch, $projectId, $todoStepCategoryId)
    {
        $pFilter = [
            'p.type' => PlanModel::TYPE_STEP_CATEGORY,
            'p.scope' => PlanModel::SCOPE_SINGLE,
            'p.end_time' => ["BETWEEN", $timeSearch]
        ];
        if (!empty($todoStepCategoryId)) {
            $pFilter['r_step_category.link_id'] = $todoStepCategoryId;
        }
        if (!empty($projectId)) {
            $pFilter['p.project_id'] = $projectId;
        }
        $episodeStepCategoryPlanList = model(PlanModel::class)->alias('p')
            ->join('task on task.id = p.task_id')
            ->join("(select * from task_relation_tag where link_module_code in ('step_category', 'show_step_category')) r_step_category on r_step_category.task_id = task.id")
            ->field('p.start_time,p.end_time,p.entity_id as episode_id,r_step_category.link_id as step_category_id')
            ->where($pFilter)
            ->group('p.entity_id,r_step_category.link_id')
            ->select();

        if (!empty($episodeStepCategoryPlanList)) {
            $todoTaskCountEpisodeStepCategoryFilter = [];
            $episodeStepCategoryPlanListGroupedByStepCategoryId = array_group_by($episodeStepCategoryPlanList, 'step_category_id');
            if ($this->isStandardProduction()) {
                foreach ($episodeStepCategoryPlanListGroupedByStepCategoryId as $stepCategoryId => $episodeStepCategoryPlanList) {
                    $todoTaskCountEpisodeStepCategoryFilter[] = [
                        'task.step_category_id' => $stepCategoryId,
                        'task.episode_id' => ['IN', array_column($episodeStepCategoryPlanList, 'episode_id')],
                    ];
                }
                if (!empty($todoTaskCountEpisodeStepCategoryFilter)) {
                    $this->appendTableList('task');
                }
            } else {
                foreach ($episodeStepCategoryPlanListGroupedByStepCategoryId as $stepCategoryId => $episodeStepCategoryPlanList) {
                    $todoTaskCountEpisodeStepCategoryFilter[] = [
                        'r_step_category.link_id' => $stepCategoryId,
                        'r_episode.link_id' => ['IN', array_column($episodeStepCategoryPlanList, 'episode_id')],
                    ];
                }
                if (!empty($todoTaskCountEpisodeStepCategoryFilter)) {
                    $this->appendTableList('r_episode');
                    $this->appendTableList('r_step_category');
                }
            }

            if (count($todoTaskCountEpisodeStepCategoryFilter) > 1) {
                $todoTaskCountEpisodeStepCategoryFilter['_logic'] = 'OR';
                $res = [$todoTaskCountEpisodeStepCategoryFilter];
            } else {
                $res = $todoTaskCountEpisodeStepCategoryFilter[0];
            }
        } else {
            $res = ['task.id' => 0];
        }
        return $res;
    }

    /**
     * 获得每日任务筛选条件
     * @return array
     */
    public function getTodayTaskFilter()
    {
//        $doneStatus = StatusService::getInstance()->getTaskDoneStatus();
        return
//            [
//            [
            ['task.plan_end_time' => ['BETWEEN', [strtotime(date("Y-m-d")), strtotime(date("Y-m-d") . ' +1 days-1seconds')]]
//                ],
//                [
//                    ['task.plan_end_time' => ['ELT', strtotime(date("Y - m - d"))],],
//                    ['task.plan_end_time' => ['GT', 0],],
//                    ['task.plan_end_time' => ['LT', strtotime(date("Y - m - d"))],],
//                    'task.end_time' => 0,
//                    "task . json->>'$.task_status'" => ["NEQ", $doneStatus['id']],
//                ],
//                '_logic' => 'or',
//            ],
            ];
    }

    /**
     * 需求管理列表过滤条件
     * @param $param
     * @param $moduleCode
     * @return array[]|mixed
     */
    public function getNoteManageListFilter($param, $moduleCode)
    {
        $filter = $param['filter'];
        $entityId = $param['entity_id'] ?? '';
        $projectId = $param['project_id'] ?? '';
        $episodeId = $param['episode_id'] ?? ''; // 集id
        $entityName = $param['entity_name'] ?? '';
        $shotStatus = $param['shot_status'] ?? ''; // 镜头状态
        $designGrade = $param['design_grade'] ?? ''; // 资产等级
        $assetStatus = $param['asset_status'] ?? ''; // 资产状态
        $showingsNumber = $param['showings_number'] ?? ''; // 场次
        $designCategory = $param['design_category'] ?? ''; // 资产类型
        $initialEpisodeCode = $param['initial_episode_code'] ?? ''; // 初始集
        $initialEpisodeCodeList = $param['initial_episode_code_list'] ?? ''; // 剧集,场次筛选
        $getAssetUseInfo = $param['get_asset_use_info'] ?? false; // 获取资产使用情况
        $storyboardRelation = $param['storyboard_relation'] ?? false; // 镜头关联
        $designDemandStatus = $param['design_demand_status'] ?? ''; // 资产需求状态
        $storyboardDemandStatus = $param['storyboard_demand_status'] ?? ''; // 镜头需求状态
        $episodeType = $param['episode_type'] ?? ''; // 集类型 本集制作/本集使用

        $entityInfo = [];
        if (!empty($entityId)) {
            $entityInfo = model(EntityModel::class)->where(['id' => $entityId])
                ->field("id,name,code,json ->> '$.design_category' as design_category")
                ->find();
        }

        if (!empty($initialEpisodeCodeList)) { // 剧集,场次筛选
            if ($episodeType == 'episode_use') { // 本集使用
                $codes = array_column($initialEpisodeCodeList, 'initial_episode_code');
                $episodeCode = model(EntityModel::class)
                    ->where(['project_id' => $projectId, 'code' => ['IN', $codes], 'module_id' => module_by_code('episode')['id']])
                    ->field('id,code')
                    ->select(); // 查询集id
                $episodeCodeMap = array_column($episodeCode, null, 'code');
                $initialEpisodeCodeList = array_map(function ($tmp) use ($episodeCodeMap) {
                    $tmp['episode_id'] = $episodeCodeMap[$tmp['initial_episode_code']]['id'] ?? 0;
                    return $tmp;
                }, $initialEpisodeCodeList);
                $relationSql = EpisodeAllocationService::getInstance()->getEpisodeShowingsSql($initialEpisodeCodeList, 'episode_id', 'showings_number');
                $relationEntityIds = model(EntityEpisodeRelationModel::class)
                    ->where(['entity_module_id' => module_by_code('design')['id']])
                    ->where(['project_id' => $projectId])
                    ->where(['_string' => $relationSql])
                    ->column('entity_id');
                if (!empty($relationEntityIds)) {
                    $filter[] = [
                        'entity.id' => ['IN', $relationEntityIds]
                    ];
                }
            } else { // 默认初始集-本集制作
                $sql = EpisodeAllocationService::getInstance()->getEpisodeShowingsSql($initialEpisodeCodeList, 'initial_episode_code', 'showings_number');
                $filter[] = ['_string' => $sql];
            }
        }
        if (!empty($moduleCode)) {
            $filter[] = [
                'module.id' => module_by_code($moduleCode)['id']
            ];
        }
        if (!empty($designDemandStatus)) { // 资产需求状态
            $filter[] = [
                "json ->> '$.design_demand_status'" => ['IN', $designDemandStatus]
            ];
        }
        if (!empty($storyboardDemandStatus)) { // 镜头资产需求状态
            $filter[] = [
                "json ->> '$.storyboard_demand_status'" => ['IN', $storyboardDemandStatus]
            ];
        }
        if (!empty($entityName)) {
            $filter[] = [
                'entity.name' => [
                    'like', '%' . $entityName . '%'
                ]
            ];
        }
        if (!empty($projectId)) {
            $filter[] = [
                'entity.project_id' => $projectId
            ];
        }
        if (!empty($initialEpisodeCode)) {
            $filter[] = [
                'entity.initial_episode_code' => ['IN', join(',', $initialEpisodeCode)]
            ];
        }
        if (!empty($showingsNumber)) {
            $filter[] = [
                'entity.showings_number' => $showingsNumber
            ];
        }
        if (!empty($assetStatus)) {
            $statusCode = model(StatusModel::class)->where(['code' => ['IN', join(',', $assetStatus)]])->column('id');
            $filter[] = [
                "entity.json ->> '$.design_status'" => ['IN', join(',', $statusCode)]
            ];
        }
        if (!empty($designGrade)) {
            $filter[] = [
                "entity.json ->> '$.design_grade'" => ['IN', join(',', $designGrade)]
            ];
        }
        if (!empty($shotStatus)) {
            $statusCode = model(StatusModel::class)->where(['code' => ['IN', join(',', $shotStatus)]])->column('id');
            $filter[] = [
                "entity.json ->> '$.storyboard_status'" => ['IN', join(',', $statusCode)]
            ];
        }
        if (!empty($designCategory)) {
            $filter[] = [
                "entity.json ->> '$.design_category'" => ['IN', join(',', $designCategory)]
            ];
        }
        if (!empty($episodeId)) {
            $episodeData = model(EntityModel::class)->where(['id' => $episodeId])->field('id,code')->find();
            $filter[] = [
                "entity.initial_episode_code" => $episodeData['code']
            ];
        }
        // 查询实体使用情况 - [角色,道具] [场景] [关卡]
        if ($getAssetUseInfo) {
            if (empty($entityInfo['design_category'])) {
                return [];
            }
            if (in_array($entityInfo['design_category'], ['角色', '道具', '关卡'])) { // 通过[角色,道具,关卡]找到当前资产下关联的镜头
                $entityData = model(EntityModel::class)->where(['id' => $entityId])->field('id,project_id,code')->find();
                $assetEntityData = model(EntityModel::class)
                    ->where([
                        'project_id' => $entityData['project_id'],
                        'code' => $entityData['code'],
                        'module_id' => ['IN', [module_by_code('asset')['id'], module_by_code('level')['id']]]
                    ])
                    ->field('id,code,project_id')->find();
                if (empty($assetEntityData['id'])) {
                    return [];
                }
                // 镜头
                if (!empty($initialEpisodeCode)) {
                    $assetEntityId = $assetEntityData['id'];
                    $entityIds = model(EntityModel::class)
                        ->where(['project_id' => $entityData['project_id'], 'entity.initial_episode_code' => ['IN', join(',', $initialEpisodeCode)], 'module_id' => module_by_code('storyboard')['id']])
                        ->where("find_in_set({$assetEntityId},json->>'$.storyboard_asset') or find_in_set({$assetEntityId},json->>'$.storyboard_level') ")
                        ->column('id');
                    if (empty($entityIds)) {
                        return [];
                    }
                }
                // 场景[关卡关联的场景]
                if (empty($initialEpisodeCode)) {
                    $designData = model(EntityModel::class)
                        ->where(['id' => $entityId])
                        ->field("id,code,project_id")
                        ->find();
                    $levelData = model(EntityModel::class)
                        ->where(['project_id' => $designData['project_id'], 'module_id' => module_by_code('level')['id']])
                        ->where(['code' => $designData['code']])
                        ->field("json ->> '$.level_asset' as level_asset_ids")
                        ->find();
                    if (empty($levelData['level_asset_ids'])) {
                        return [];
                    }
                    $entityIds = explode(',', $levelData['level_asset_ids']);
                    // 资产转概念
                    $assetEntityData = model(EntityModel::class)->where(['id' => ['IN', $entityIds]])->field("JSON_UNQUOTE(JSON_EXTRACT(json, '$.asset_design')) as asset_design")->select();
                    $entityIds = array_column($assetEntityData, 'asset_design');
                    if (empty($entityIds)) {
                        return [];
                    }
                }
                return [
                    'entity.id' => ['IN', $entityIds]
                ];
            }
            if ($entityInfo['design_category'] == '场景') { // 通过[场景]找到当前资产下关联的关卡

                $scenarioName = $entityInfo['name'];
                $levelIds = model(EntityModel::class)
                    ->where(['project_id' => $projectId, 'module_id' => module_by_code('design')['id']])
                    ->where(["json->>'$.design_category'" => '关卡'])
                    ->where("find_in_set('{$scenarioName}',json->>'$.level_relate_asset')")
                    ->column('id');
                if (empty($levelIds)) {
                    return [];
                }
                $filter = [
                    'entity.id' => ['IN', $levelIds]
                ];
            }
        }
        if ($storyboardRelation) { // 查看镜头关联
            $entityAssetData = model(EntityModel::class)
                ->where(['id' => $entityId])
                ->field("json ->> '$.storyboard_asset' as storyboard_asset_ids,json ->> '$.storyboard_level' as storyboard_level_ids")
                ->find();
            $entityAssetIds = '';
            if (!empty($entityAssetData['storyboard_asset_ids'])) {
                $entityAssetIds .= $entityAssetData['storyboard_asset_ids'];
            }
            if (!empty($entityAssetData['storyboard_level_ids'])) {
                $entityAssetIds .= ',' . $entityAssetData['storyboard_level_ids'];
            }
            $entityAssetIds = trim($entityAssetIds, ',');
            if (empty($entityAssetIds)) {
                return [];
            }
            $entityRelationJsonList = model(EntityModel::class)
                ->where(['id' => ['IN', $entityAssetIds]])
                ->field('id,module_id,json')
                ->select();
            if (empty($entityRelationJsonList)) {
                return [];
            }
            $designIdList = [];
            foreach ($entityRelationJsonList as $entityRelationJson) {
                $entityRelationJsonModule = module_by_id($entityRelationJson['module_id']);
                if (empty($entityRelationJsonModule)) {
                    continue;
                }
                $entityRelationJson = json_decode($entityRelationJson['json'], true);
                if (empty($entityRelationJson[$entityRelationJsonModule['code'] . '_design'])) {
                    continue;
                }
                $designIdList[] = intval($entityRelationJson[$entityRelationJsonModule['code'] . '_design']);
            }

            if (empty($designIdList)) {
                return [];
            }
            $filter = [
                'entity.id' => ['IN', $designIdList]
            ];
        }
        return $filter;
    }
}
